package com.xqboss.apps.service.user;

import cn.hutool.core.lang.Assert;
import cn.hutool.core.util.ObjUtil;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.xqboss.apps.constant.LockKey;
import com.xqboss.apps.domain.user.UserAssetLidou;
import com.xqboss.apps.domain.user.UserAssetLidouRecord;
import com.xqboss.apps.enums.user.WalletChangeDirectionEnum;
import com.xqboss.apps.enums.user.WalletLidouChangeTypeEnum;
import com.xqboss.apps.mapper.user.UserAssetLidouMapper;
import com.xqboss.common.core.domain.entity.SysUser;
import com.xqboss.common.core.redis.lock.LockValue;
import com.xqboss.common.core.redis.lock.RedisLock;
import com.xqboss.common.exception.ServiceException;
import com.xqboss.common.utils.SecurityUtils;
import com.xqboss.system.service.ISysUserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;

@Service
public class UserAssetLidouService extends ServiceImpl<UserAssetLidouMapper, UserAssetLidou> {

    @Autowired
    private UserAssetLidouRecordService userAssetLidouRecordService;

    @Autowired
    private ISysUserService sysUserService;

    /**
     * 力豆余额修改
     *
     * @param userId
     * @param changeTypeEnum
     * @param directionEnum
     * @param amount
     * @param sourceId
     * @param remark
     * @return 记录id
     */
    @Transactional
    @RedisLock(lockKey = LockKey.LOCK_USER_ASSET_LIDOU)
    public Long updateLidouBalance(@LockValue Long userId,
                                    WalletLidouChangeTypeEnum changeTypeEnum,
                                    WalletChangeDirectionEnum directionEnum,
                                    BigDecimal amount,
                                    Long sourceId,
                                    String remark) {
        if (amount != null && amount.compareTo(BigDecimal.ZERO) < 1) {
            return null;
        }
        if (userId == null || changeTypeEnum == null || directionEnum == null
                || amount == null || amount.compareTo(BigDecimal.ZERO) < 1) {
            throw new ServiceException("力豆余额修改参数错误~");
        }
        UserAssetLidou wrench = this.lambdaQuery().eq(UserAssetLidou::getUserId, userId).one();
        if (ObjUtil.isEmpty(wrench)) {
            wrench = new UserAssetLidou();
            wrench.setUserId(userId);
            this.save(wrench);
        }
        if (directionEnum == WalletChangeDirectionEnum.OUT) {
            if (amount.compareTo(wrench.getAmount()) > 0) {
                throw new ServiceException("力豆余额不足~");
            }
            amount = amount.negate();
        }
        boolean result = this.lambdaUpdate()
                .setSql("amount = amount +" + amount)
                .eq(UserAssetLidou::getId, wrench.getId())
                .apply("(amount + {0}) >= 0", amount)
                .update();
        Assert.isTrue(result, () -> new ServiceException("力豆更新失败~"));
        UserAssetLidouRecord record = new UserAssetLidouRecord();
        record.setUserId(userId);
        record.setWalletId(wrench.getId());
        record.setAmount(amount.abs());
        record.setAmountAfter(wrench.getAmount().add(amount));
        record.setAmountBefore(wrench.getAmount());
        record.setDirection(directionEnum);
        record.setChangeType(changeTypeEnum);
        record.setSourceId(sourceId);
        try {
            Long operateUserId = SecurityUtils.getUserId();
            record.setOperateUserId(operateUserId);
        } catch (Exception e) {
        }
        record.setRemark(remark);
        result = userAssetLidouRecordService.save(record);
        Assert.isTrue(result, () -> new ServiceException("力豆更新失败！"));

        return record.getId();
    }

    /**
     * 注册时，添加力豆钱包
     *
     * @param username 手机号
     */
    public void addLidouByUserName(String username) {
        Assert.notNull(username,()->new ServiceException("用户名不能为空~"));
        SysUser user = sysUserService.selectUserByUserName(username);
        if (user == null) {
            return;
        }
        UserAssetLidou lidou = new UserAssetLidou();
        lidou.setUserId(user.getUserId());
        this.save(lidou);
    }

    /**
     * 获取力豆钱包信息
     *
     * @param userId 用户id
     * @return 力豆钱包信息
     */
    public UserAssetLidou getLidouInfo(Long userId){
        Assert.notNull(userId,()->new ServiceException("用户名不能为空~"));
        UserAssetLidou userAssetLidou = this.lambdaQuery().eq(UserAssetLidou::getUserId, userId).one();
        if (ObjUtil.isEmpty(userAssetLidou)) {
            userAssetLidou = new UserAssetLidou();
            userAssetLidou.setUserId(userId);
            this.save(userAssetLidou);
        }
        return userAssetLidou;
    }
}
